﻿using DefaultDspPlugins.UI.Common.Modulizer.Engine.GUI;
using DefaultDspPlugins.UI.Common.Modulizer.Engine.GUIv2.FrontEndComponents;
using SharpDepend.Datatypes;
using System;
using System.Collections.Generic;
using ZquenceStudio3Host.Graphics.Components;
using ZquenceStudio3Host.Graphics.GUI;

namespace DefaultDspPlugins.UI.Common.Modulizer.Engine.GUIv2.Editors
{
    internal class ModuleUIEditorWindow : BaseUIEditorWindow
    {
        private ModuleUIPanel mCurrentModuleUI;
        private Listbox2 ComponentExplorer;
        private ModuleUIToolsPanel Tools;
        private PropertiesEditor Properties;
        private ZoomablePanel ModuleUIViewer;
        private Panel ModuleUIViewer_SelectorLayer;
        private Panel Selector;

        private const int ITEM_HEIGHT = 24;

        public event Action<BaseModuleUI> ModuleUIUpdated;

        public ModuleUIEditorWindow(BasicGuiManager engineCore) : base(engineCore)
        {
            BackgroundColor = SharpDepend.Datatypes.Color.Transparent;

            ComponentExplorer = new Listbox2(engineCore);
            ComponentExplorer.OnSelectedListboxItem += ComponentExplorer_OnSelectedListboxItem;
            ComponentExplorer.SetItemHeight(ITEM_HEIGHT);
            ComponentExplorer.BackgroundColor = new SharpDepend.Datatypes.Color(253, 60, 60, 60);
            ComponentExplorer.DimensionInProcent = true;
            ComponentExplorer.Width = 20;
            ComponentExplorer.Height = 100;
            AddPart(ComponentExplorer);
        }

        protected override void OnComponentInitialize()
        {
            Tools = new ModuleUIToolsPanel(EngineCore);
            Tools.PanelUpdated += Tools_PanelUpdated;
            Tools.BackgroundColor = new SharpDepend.Datatypes.Color(253, 70, 70, 70);
            Tools.DimensionInProcent = true;
            Tools.X = 20;
            Tools.Width = 20;
            Tools.Height = 100;
            AddPart(Tools);

            Properties = new PropertiesEditor(EngineCore);
            Properties.PropertyChanged += Properties_PropertyChanged;
            Properties.BackgroundColor = new SharpDepend.Datatypes.Color(253, 60, 60, 60);
            Properties.DimensionInProcent = true;
            Properties.X = 40;
            Properties.Width = 20;
            Properties.Height = 100;
            AddPart(Properties);

            ModuleUIViewer = new ZoomablePanel(EngineCore);
            ModuleUIViewer.BackgroundColor = Color.DarkGray;
            //ModuleUIViewer.SetTexture("Images/TextilBackgroundBlack.png");
            ModuleUIViewer.DimensionInProcent = true;
            ModuleUIViewer.X = 60;
            ModuleUIViewer.Width = 40;
            ModuleUIViewer.Height = 100;
            AddPart(ModuleUIViewer);

            ModuleUIViewer_SelectorLayer = new ZoomablePanel(EngineCore);
            ModuleUIViewer_SelectorLayer.BackgroundColor = Color.Transparent;
            ModuleUIViewer_SelectorLayer.DimensionInProcent = true;
            ModuleUIViewer_SelectorLayer.X = 60;
            ModuleUIViewer_SelectorLayer.Width = 40;
            ModuleUIViewer_SelectorLayer.Height = 100;

            Selector = new Panel(EngineCore);
            Selector.BackgroundColor = new Color(100, 150, 100, 100);
            Selector.Visible = false;
            ModuleUIViewer_SelectorLayer.AddPart(Selector);
        }

        private void Tools_PanelUpdated()
        {
            UpdateComponentExplorer(mCurrentModuleUI);

            ModuleUIUpdated?.Invoke(mCurrentModuleUI.ModuleUI);
        }

        private void Properties_PropertyChanged()
        {
            mCurrentModuleUI.SaveStructure();

            ModuleUIUpdated?.Invoke(mCurrentModuleUI.ModuleUI);
        }

        /// <summary>
        /// Calls when user select a item.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="selectedItem"></param>
        private void ComponentExplorer_OnSelectedListboxItem(object sender, Listbox2Item selectedItem)
        {
            BaseObject component = (BaseObject)selectedItem.ItemObject;

            UpdateProperties(component);

            SelectPanel(component);
        }

        private void SelectPanel(BaseObject component)
        {
            Selector.DimensionInProcent = component.DimensionInProcent;
            Selector.X = component.X;
            Selector.Y = component.Y;
            Selector.Width = component.Width;
            Selector.Height = component.Height;
            Selector.Visible = true;
        }

        /// <summary>
        /// Get or set the current moudle UI for viewing and editing.
        /// </summary>
        public ModuleUIPanel CurrentModuleUI
        {
            get { return mCurrentModuleUI; }
            set
            {
                mCurrentModuleUI = value;

                ModuleUIViewer.Content = value;

                UpdateComponentExplorer(value);
                UpdateProperties(value);
            }
        }

        private void UpdateProperties(BaseObject moduleUI)
        {
            Properties.EditablePanel = moduleUI;
            Tools.EditablePanel = moduleUI;
        }

        void UpdateComponentExplorer(ModuleUIPanel moduleUI)
        {
            ComponentExplorer.Clear();
            
            FillComponentTree(moduleUI);

            ComponentExplorer.Expand();
        }
        
        void FillComponentTree(BaseObject component)
        {
            Listbox2Item item = CreateItem(ComponentExplorer, component);

            FillComponentTree(item, component.GetComponents());
        }

        void FillComponentTree(Listbox2Item inTtem, IEnumerable<BaseObject> components)
        {
            foreach (BaseObject component in components)
            {
                Listbox2Item item = CreateItem(inTtem, component);

                FillComponentTree(item, component.GetComponents());
            }
        }

        private Listbox2Item CreateItem(Listbox2Item inTtem, BaseObject component)
        {
            Listbox2Item item = new Listbox2Item(EngineCore, component.ToString(), component);
            item.OnSelectedListboxItem += ComponentExplorer_OnSelectedListboxItem;
            item.SetItemHeight(ITEM_HEIGHT);
            inTtem.AddItem(item);
            return item;
        }
    }
}
